package com.miniserver.tql.database.impl;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import com.miniserver.tql.database.EngineContext;
import com.miniserver.tql.database.EngineFunction;
import com.miniserver.util.HashUtility;
import com.miniserver.util.cache.MemCacheManager;

public class EngineFunctionImpl implements EngineFunction {

	@Override
	public String eval(EngineContext context, String expr) {
		if (expr.isEmpty()) {
			return "";
		}
		char ch = expr.charAt(expr.length() - 1);
		if (ch == ')') {
			int pos = expr.indexOf('(');
			if (pos < 0) {
				return expr;
			}
			//
			if (pos == 0) {
				String subExpr = expr.substring(pos + 1, expr.length() - 1);
				return this.eval(context, subExpr);
			} else {
				String subExpr = expr.substring(pos + 1, expr.length() - 1);
				return execFunc(context, expr.substring(0, pos), subExpr);
			}
		} else if (ch == '\'') {
			if (expr.charAt(0) != '\'') {
				return expr;
			} else {
				return expr.substring(1, expr.length() - 1);
			}
		} else if (ch == '\"') {
			if (expr.charAt(0) != '\"') {
				return expr;
			} else {
				return expr.substring(1, expr.length() - 1);
			}
		} else {
			ch = expr.charAt(0);
			if (ch == '@' || ch == '?') {
				if (expr.indexOf(".") > 0) {
					StringBuffer keyBuffer = new StringBuffer();
					String[] vals = expr.split("\\.");
					String[] keys = vals[0].split("\\$\\$");
					for (String key : keys) {
						if (key.startsWith("?") || key.startsWith("@")) {
							keyBuffer.append(context.get(key));
						} else {
							keyBuffer.append(key);
						}
					}
					return MemCacheManager.getValue(keyBuffer.toString(), vals[1]);
				} else {
					return context.get(expr);
				}
			} else {
				return expr;
			}
		}
	}

	private String execFunc(EngineContext context, String func, String expr) {
		if (func.equals("inexpr")) {
			return this.inexpr(context, expr);
		} else if (func.equals("add")) {
			return this.add(context, expr);
		} else if (func.equals("sub")) {
			return this.sub(context, expr);
		} else if (func.equals("mul")) {
			return this.mul(context, expr);
		} else if (func.equals("div")) {
			return this.div(context, expr);
		} else if(func.equals("encrypt")){
			return this.encrypt(context, expr);
		} 
		else {
			return "";
		}
	}

	private String inexpr(EngineContext context, String expr) {
		if (expr.isEmpty()) {
			return "";
		}
		//
		String[] p=expr.split(",");
		String exprValue = this.eval(context, p[0].trim());
		String type = p.length > 1 ? this.eval(context, p[1].trim()) : "string";
		StringBuilder inexpr = new StringBuilder();
		if(type.equalsIgnoreCase("number")){
			String t = exprValue.replace(",,", ",");
			while(t.length() != exprValue.length()) {
				exprValue = t;
				t = exprValue.replace(",,", ",");
			}
			exprValue = exprValue.replaceAll("^\\,", "").replaceAll(",$", "");
			inexpr.append(exprValue);
		}else if(type.equalsIgnoreCase("string")){
			String[] values = exprValue.replace("\"", "\'\"").split(",");
			
			inexpr.append('\'').append(values[0]);
			for (int i = 1; i < values.length; i++) {
				inexpr.append("\',\'").append(values[i]);
			}
			inexpr.append("\'");
		}

		return inexpr.toString();
	}

	private String add(EngineContext context, String expr) {
		String[] p = expr.split(",");
		String p1v = this.eval(context, p[0].trim());
		String p2v = this.eval(context, p[1].trim());
		String type = p.length > 2 ? this.eval(context, p[2].trim()) : "string";
		if (type.equalsIgnoreCase("int")) {
			Integer result = Integer.parseInt(p1v) + Integer.parseInt(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("long")) {
			Long result = Long.parseLong(p1v) + Long.parseLong(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("float")) {
			Float result = Float.parseFloat(p1v) + Float.parseFloat(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("double")) {
			Double result = Double.parseDouble(p1v) + Double.parseDouble(p2v);
			return result.toString();
		} else {
			return p1v + p2v;
		}
	}

	private String sub(EngineContext context, String expr) {
		String[] p = expr.split(",");
		String p1v = this.eval(context, p[0].trim());
		String p2v = this.eval(context, p[1].trim());
		String type = p.length > 2 ? this.eval(context, p[2].trim()) : "double";
		if (type.equalsIgnoreCase("int")) {
			Integer result = Integer.parseInt(p1v) - Integer.parseInt(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("long")) {
			Long result = Long.parseLong(p1v) - Long.parseLong(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("float")) {
			Float result = Float.parseFloat(p1v) - Float.parseFloat(p2v);
			return result.toString();
		} else {
			Double result = Double.parseDouble(p1v) - Double.parseDouble(p2v);
			return result.toString();
		}
	}

	private String mul(EngineContext context, String expr) {
		String[] p = expr.split(",");
		String p1v = this.eval(context, p[0].trim());
		String p2v = this.eval(context, p[1].trim());
		String type = p.length > 2 ? this.eval(context, p[2].trim()) : "double";
		if (type.equalsIgnoreCase("int")) {
			Integer result = Integer.parseInt(p1v) * Integer.parseInt(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("long")) {
			Long result = Long.parseLong(p1v) * Long.parseLong(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("float")) {
			Float result = Float.parseFloat(p1v) * Float.parseFloat(p2v);
			return result.toString();
		} else {
			Double result = Double.parseDouble(p1v) * Double.parseDouble(p2v);
			return result.toString();
		}
	}

	private String div(EngineContext context, String expr) {
		String[] p = expr.split(",");
		String p1v = this.eval(context, p[0].trim());
		String p2v = this.eval(context, p[1].trim());
		String type = p.length > 2 ? this.eval(context, p[2].trim()) : "double";
		if (type.equalsIgnoreCase("int")) {
			Integer result = Integer.parseInt(p1v) / Integer.parseInt(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("long")) {
			Long result = Long.parseLong(p1v) / Long.parseLong(p2v);
			return result.toString();
		} else if (type.equalsIgnoreCase("float")) {
			Float result = Float.parseFloat(p1v) / Float.parseFloat(p2v);
			return result.toString();
		} else {
			Double result = Double.parseDouble(p1v) / Double.parseDouble(p2v);
			return result.toString();
		}
	}
	
	private String encrypt(EngineContext context, String expr){
        String resultString=new String();
        expr=this.eval(context, expr);
		try {
	           byte[] btInput = expr.getBytes();
	            // 获得MD5摘要算法的 MessageDigest 对象
	            MessageDigest mdInst = MessageDigest.getInstance("MD5");
	            // 使用指定的字节更新摘要
	            mdInst.update(btInput);
	            // 获得密文
	            byte[] md = mdInst.digest();
	        resultString=HashUtility.bytesToHexString(md);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
         return resultString;
	}
}
